#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
Simplified BSD License (BSD)
Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this 
      list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice, 
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 12-Nov-09 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;

using Thn;
#endregion

namespace Thn.Interface.Vcl
{
    /// <summary>
    /// Base class for pages
    /// </summary>
    [ToolboxItem(false), DefaultEvent("IsModifiedChanged")]
#if DEBUG
    public
#else
    public
#endif
 class Page : PageBase
    {
        #region Fields
        #endregion

        #region Properties

        #region Is Modified
        private bool mIsModified = false;
        /// <summary>
        /// Gets/Sets whether content of this page has been modified.
        /// If true, the next call to OnInvalidate() will return false.
        /// </summary>
        [Browsable(true), DefaultValue(false), Category("Behavior"), Description("If true, next call to OnInvalidate() will return false")]
        public bool IsModified
        {
            get { return mIsModified; }
            set
            {
                if (mIsModified != value)
                {
                    mIsModified = value;
                    RaiseIsModifiedChanged(EventArgs.Empty);
                }
            }
        }
        #endregion

        #region Is Authenticated
        /// <summary>
        /// Checks whether the current user has logged in.
        /// </summary>
        [Browsable(false)]
        public bool IsAuthenticated
        {
            get { return OnCheckAuthentication(); }
        }
        #endregion

        #region Can View
        /// <summary>
        /// Checks whether the current user has permission to view this page.
        /// </summary>
        [Browsable(false)]
        public bool CanView
        {
            get { return OnCheckViewPermission(); }
        }
        #endregion

        #region Unauthenticated Page
        private string mUnauthenticatedPage = "";
        /// <summary>
        /// Gets/Sets ID of the page to redirect user to when user is not logged in.
        /// </summary>
        [Browsable(true), DefaultValue(""), Category("Security"), Description("ID of the page to redirect user to when user is not logged in.")]
        public string UnauthenticatedPage
        {
            get { return mUnauthenticatedPage; }
            set { mUnauthenticatedPage = value; }
        }
        #endregion

        #region Unauthorized Page
        private string mUnauthorizedPage = "";
        /// <summary>
        /// Gets/Sets ID of the page to redirect user to when user is not allowed to view this page.
        /// </summary>
        [Browsable(true), DefaultValue(""), Category("Security"), Description("ID of the page to redirect user to when user is not allowed to view.")]
        public string UnauthorizedPage
        {
            get { return mUnauthorizedPage; }
            set { mUnauthorizedPage = value; }
        }
        #endregion

        #endregion

        #region Events

        #region Is Modified Changed
        /// <summary>
        /// This event is raised after property IsModified has been changed.
        /// </summary>
        public event EventHandler IsModifiedChanged;

        /// <summary>
        /// Invoke event IsModifiedChanged
        /// </summary>
        protected void RaiseIsModifiedChanged(EventArgs args)
        {
            EventHandler handler = IsModifiedChanged;
            if (handler != null) handler(this, args);
        }
        #endregion

        #endregion

        #region On Allow Navigation Away
        /// <summary>
        /// Checks to see if user can navigate away from this page.
        /// <para>If return false, this page should call ResumeLastNavigateRequest() to permit last request.</para>
        /// </summary>
        /// <returns>True if allowed, false otherwise.</returns>
        protected override bool OnAllowNavigationAway()
        {
            return !mIsModified;
        }
        #endregion

        #region On Check Authentication
        /// <summary>
        /// Checks whether user has logged in.
        /// </summary>
        protected virtual bool OnCheckAuthentication()
        {
            return true;
        }
        #endregion

        #region On Check View Permission
        /// <summary>
        /// Check whether user is authorized to view this page.
        /// </summary>
        protected virtual bool OnCheckViewPermission()
        {
            return true;
        }
        #endregion

        #region Process Allow View
        /// <summary>
        /// Checks whether the current user is authorized to view this page.
        /// </summary>
        /// <param name="redirection">When returned result is false. This page may use the redirection as
        /// ID of the page the user will be redirected to.</param>
        public override bool ProcessAllowView(ref string redirection)
        {
            bool result = false;

            if (IsAuthenticated)
            {
                if (CanView)
                {
                    #region Everything looks good, allow to view this page
                    result = true;
                    #endregion
                }
                else
                {
                    #region Not allowed to view
                    redirection = mUnauthorizedPage;
                    #endregion
                }
            }
            else
            {
                #region Not logged in yet
                redirection = mUnauthenticatedPage;                
                #endregion
            }

            return result;
        }
        #endregion

        #region On Render Content
        /// <summary>
        /// Paint the control's content (text, value, data, etc.) onto canvas.
        /// </summary>
        /// <param name="canvas">The canvas on which to paint the control.</param>
        /// <param name="renderer">The optional renderer for the selected theme.</param>
        /// <param name="context">The current drawing context.</param>
        protected override void OnRenderContent(Graphics canvas, IControlRenderer renderer, RenderContext context)
        {

        }
        #endregion

        #region On Render Visual
        /// <summary>
        /// Paint the control's visual stuff (border, background, etc.) onto canvas.
        /// </summary>
        /// <param name="canvas">The canvas on which to paint the control.</param>
        /// <param name="renderer">The optional renderer for the selected theme.</param>
        /// <param name="context">The current drawing context.</param>
        protected override void OnRenderVisual(Graphics canvas, IControlRenderer renderer, RenderContext context)
        {
            //DrawBackground(canvas);

            if (DesignMode)
            {
                Rectangle r = new Rectangle(0, 0, Width - 1, Height - 1);
                DrawFocusedCues(canvas, r, context);
            }
            #region Defensive tracing
            else
            {
                //no need to render visual cues at runtime
            }
            #endregion
        }
        #endregion

        #region Draw Focused Cues
        /// <summary>
        /// Render a dotted rectangle around the boundary of a control to indicate the control currently
        /// receives focus.
        /// </summary>
        protected void DrawFocusedCues(Graphics canvas, Rectangle r, RenderContext context)
        {
            Pen p = new Pen(Color.FromArgb(89, 152, 203));
            p.Width = 1.5f;
            p.DashStyle = DashStyle.Dot;
            canvas.DrawRectangle(p, r);
            p.Dispose();
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor.
        /// </summary>
        public Page()
        {
            //Ask the Control to double-buffer this whole page
            //for faster display
            this.DoubleBuffered = true;
            CacheBackground = false;
            BackgroundImageLayout = ImageLayout.Stretch;
        }
        #endregion
    }
}
